package com.espressif.iot.esptouch.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import com.espressif.iot.esptouch.task.__IEsptouchTask;

import android.util.Log;

/**
 * this class is used to help send UDP data according to length
 * 
 * @author afunx
 * 
 */
public class UDPSocketClient
{
    
    private static final String TAG = "UDPSocketClient";
    
    private DatagramSocket mSocket;
    
    private volatile boolean mIsStop;
    
    private volatile boolean mIsClosed;
    
    public UDPSocketClient()
    {
        try
        {
            this.mSocket = new DatagramSocket();
            this.mIsStop = false;
            this.mIsClosed = false;
        }
        catch (SocketException e)
        {
            if (__IEsptouchTask.DEBUG)
            {
                Log.e(TAG, "SocketException");
            }
            e.printStackTrace();
        }
    }
    
    @Override
    protected void finalize()
        throws Throwable
    {
        close();
        super.finalize();
    }
    
    public void interrupt()
    {
        if (__IEsptouchTask.DEBUG)
        {
            Log.i(TAG, "USPSocketClient is interrupt");
        }
        this.mIsStop = true;
    }
    
    /**
     * close the UDP socket
     */
    public synchronized void close()
    {
        if (!this.mIsClosed)
        {
            this.mSocket.close();
            this.mIsClosed = true;
        }
    }
    
    /**
     * send the data by UDP
     * 
     * @param data the data to be sent
     * @param targetHost the host name of target, e.g. 192.168.1.101
     * @param targetPort the port of target
     * @param interval the milliseconds to between each UDP sent
     */
    public void sendData(byte[][] data, String targetHostName, int targetPort, long interval)
    {
        sendData(data, 0, data.length, targetHostName, targetPort, interval);
    }
    
    /**
     * send the data by UDP
     * 
     * @param data the data to be sent
     * @param offset the offset which data to be sent
     * @param count the count of the data
     * @param targetHost the host name of target, e.g. 192.168.1.101
     * @param targetPort the port of target
     * @param interval the milliseconds to between each UDP sent
     */
    public void sendData(byte[][] data, int offset, int count, String targetHostName, int targetPort, long interval)
    {
        if ((data == null) || (data.length <= 0))
        {
            if (__IEsptouchTask.DEBUG)
            {
                Log.e(TAG, "sendData(): data == null or length <= 0");
            }
            return;
        }
        for (int i = offset; !mIsStop && i < offset + count; i++)
        {
            if (data[i].length == 0)
            {
                continue;
            }
            try
            {
                // Log.i(TAG, "data[" + i + " +].length = " + data[i].length);
                DatagramPacket localDatagramPacket =
                    new DatagramPacket(data[i], data[i].length, InetAddress.getByName(targetHostName), targetPort);
                this.mSocket.send(localDatagramPacket);
            }
            catch (UnknownHostException e)
            {
                if (__IEsptouchTask.DEBUG)
                {
                    Log.e(TAG, "sendData(): UnknownHostException");
                }
                e.printStackTrace();
                mIsStop = true;
                break;
            }
            catch (IOException e)
            {
                if (__IEsptouchTask.DEBUG)
                {
                    Log.e(TAG, "sendData(): IOException, but just ignore it");
                }
                // for the Ap will make some troubles when the phone send too many UDP packets,
                // but we don't expect the UDP packet received by others, so just ignore it
            }
            try
            {
                Thread.sleep(interval);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
                if (__IEsptouchTask.DEBUG)
                {
                    Log.e(TAG, "sendData is Interrupted");
                }
                mIsStop = true;
                break;
            }
        }
        if (mIsStop)
        {
            close();
        }
    }
}
